package main

import (
	"fmt"
	"log"
	"strconv"

	"github.com/go-micro/plugins/v4/registry/consul"
	opentracingTool "github.com/go-micro/plugins/v4/wrapper/trace/opentracing"

	"github.com/go-micro/plugins/v4/wrapper/ratelimiter/ratelimit"
	jujuratelimit "github.com/juju/ratelimit"

	"github.com/opentracing/opentracing-go"
	"go-micro.dev/v4"
	"go-micro.dev/v4/registry"

	"gitee.com/go-micro-services/cart/domain/repository"
	"gitee.com/go-micro-services/cart/domain/service"
	"gitee.com/go-micro-services/cart/handler"
	pbcart "gitee.com/go-micro-services/cart/proto/cart"
	"gitee.com/go-micro-services/common"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

var (
	serviceName     = "go.micro.service.cart"
	version         = "latest"
	host            = "127.0.0.1"
	port            = 8500
	address         = host + ":" + strconv.Itoa(port)
	mysqlConfigPath = "/micro/config/mysql"
)

func main() {
	// 1. 指定注册中心
	consulReg := consul.NewRegistry(
		registry.Addrs(address),
	)

	// 2. 从配置中心获取mysql配置并创建处理
	mysqlConfig, consulConfigErr := common.GetConsulMysqlConfig(address, mysqlConfigPath)
	if consulConfigErr != nil {
		log.Fatal(consulConfigErr)
	}
	mysqlUrl := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", mysqlConfig.User, mysqlConfig.Pwd, mysqlConfig.Host, mysqlConfig.Port, mysqlConfig.Database)
	db, dbErr := gorm.Open("mysql", mysqlUrl)
	if dbErr != nil {
		log.Fatal(dbErr)
	}
	defer db.Close()

	rp := repository.NewCartRepository(db)
	// 数据库表初始化，只执行一次, 如果本来就设计好了，则无需下面
	// rp.InitTable()
	// db.SingularTable(false) // true 则 表就是单数

	// 3. 链路追踪配置
	tracer, closer, tracerErr := common.NewTracer("go.micro.service.cart", "localhost:6831")
	if tracerErr != nil {
		log.Fatal(tracerErr)
	}
	defer closer.Close()
	opentracing.SetGlobalTracer(tracer)

	// 4. 创建服务实例
	cartDataService := service.NewCartDataService(rp)

	// 5. 创建服务和初始化
	srv := micro.NewService()
	srv.Init(
		micro.Name(serviceName),
		micro.Version(version),
		micro.Registry(consulReg),
		// micro.Address("0.0.0.0:8087"), // 暴露的服务地址 这里可用可不用指定
		micro.WrapHandler(opentracingTool.NewHandlerWrapper(opentracing.GlobalTracer())),       // 绑定链路追踪
		micro.WrapHandler(ratelimit.NewHandlerWrapper(jujuratelimit.NewBucket(50, 100), true)), // 添加限流
	)

	// 6. 注册 handler
	if handlerErr := pbcart.RegisterCartHandler(srv.Server(), &handler.Cart{CartDataService: cartDataService}); handlerErr != nil {
		log.Fatal(handlerErr)
	}

	// 7. 运行服务
	if runErr := srv.Run(); runErr != nil {
		log.Fatal(runErr)
	}
}
